﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.ServiceModel.Syndication;
using System.ServiceModel.Web;
using System.Net;
using System.Web;
using System.Xml;
using ScottLane.MediaFeeder.ObjectModel;

namespace ScottLane.MediaFeeder.WebService
{
    /// <summary>
    /// Partial class of MediaService that implements the Album related methods.
    /// </summary>
    /// <remarks>
    /// Querying: http://msdn.microsoft.com/en-us/library/bb248951(VS.85).aspx
    /// </remarks>
    public partial class MediaService : IMediaService
    {
        /// <summary>
        /// Get a feed of the specified album.
        /// </summary>
        /// <param name="albumID">The album identifier.</param>
        /// <returns>The album feed.</returns>
        public SyndicationFeedFormatter GetAlbum(string albumID)
        {
            string decodedAlbumID = HttpUtility.UrlDecode(albumID);

            if (!Album.Exists(decodedAlbumID))
            {
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
                return null;
            }

            Album album = new Album(decodedAlbumID);
            SyndicationFeed feed = new SyndicationFeed();
            feed.Title = new TextSyndicationContent(album.Artist + " - " + album.Title);
            feed.Description = new TextSyndicationContent(album.Artist + " - " + album.Title);
            feed.Links.Add(SyndicationLink.CreateAlternateLink(new Uri("http://code.google.com/p/mediafeeder/wiki/Album")));
            feed.Generator = XmlString.Generator;
            feed.AttributeExtensions.Add(new XmlQualifiedName(XmlString.ITunesLocalName, XmlString.GenericNameSpace), XmlString.ITunesNamespace);
            feed.AttributeExtensions.Add(new XmlQualifiedName(XmlString.MediaFeederLocalName, XmlString.GenericNameSpace), XmlString.MediaFeederNamespace);

            if (album.ImageFileName != null)
            {
                string friendlyFileName = Path.GetFileName(album.ImageFileName).Replace("#", "");
                string imageUrl = Utility.BaseUrl + "/music/albums/" + HttpUtility.UrlEncode(album.AlbumID) + "/image/" + friendlyFileName;
                feed.ImageUrl = new Uri(imageUrl);
                feed.Links.Add(SyndicationLink.CreateAlternateLink(feed.ImageUrl));
            }

            List<SyndicationItem> items = new List<SyndicationItem>();
            items.Add(new AlbumSyndicationItem(album));
            feed.Items = items;
            return Utility.GetFormatter(feed);
        }

        /// <summary>
        /// Gets an album image.
        /// </summary>
        /// <param name="albumID">The album identifier.</param>
        /// <returns>The album image.</returns>
        public Stream GetAlbumImage(string albumID)
        {
            string decodedAlbumID = HttpUtility.UrlDecode(albumID);

            if (!Album.Exists(decodedAlbumID))
            {
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
                return null;
            }

            Album album = new Album(decodedAlbumID);
            FileInfo imageFile = new FileInfo(album.ImageFileName);

            if (!imageFile.Exists)
            {
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
                return null;
            }

            WebOperationContext.Current.OutgoingResponse.ContentType = MimeType.FromExtension(imageFile.Extension);
            WebOperationContext.Current.OutgoingResponse.ContentLength = imageFile.Length;
            return imageFile.OpenRead();
        }

        /// <summary>
        /// Gets a feed of songs in the specified album.
        /// </summary>
        /// <param name="albumID">The album identifier.</param>
        /// <param name="startIndex"></param>
        /// <param name="maxResults"></param>
        /// <returns>The song feed.</returns>
        public SyndicationFeedFormatter GetAlbumSongs(string albumID, string startIndex, string maxResults)
        {
            string decodedAlbumID = HttpUtility.UrlDecode(albumID);

            if (!Album.Exists(decodedAlbumID))
            {
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
                return null;
            }

            Album album = new Album(decodedAlbumID);
            SyndicationFeed feed = new SyndicationFeed();
            string feedTitle = album.Title;
            string feedDescription = "Songs from the album '" + album.Title + "'";

            if (album.Artist != null)
            {
                feedTitle = album.Artist + " - " + feedTitle;
                feedDescription = feedDescription + " by " + album.Artist;
            }

            feed.Title = new TextSyndicationContent(feedTitle);
            feed.Description = new TextSyndicationContent(feedDescription);
            feed.Links.Add(SyndicationLink.CreateAlternateLink(new Uri("http://code.google.com/p/mediafeeder/wiki/AlbumSongs")));
            feed.Generator = XmlString.Generator;
            feed.AttributeExtensions.Add(new XmlQualifiedName(XmlString.ITunesLocalName, XmlString.GenericNameSpace), XmlString.ITunesNamespace);
            feed.AttributeExtensions.Add(new XmlQualifiedName(XmlString.MediaFeederLocalName, XmlString.GenericNameSpace), XmlString.MediaFeederNamespace);
            List<SyndicationItem> items = new List<SyndicationItem>();

            int parsedStartIndex = 0;
            int.TryParse(startIndex, out parsedStartIndex);

            int parsedMaxResults = 0;
            int.TryParse(maxResults, out parsedMaxResults);

            int finishIndex = album.Songs.Count - 1;

            if (parsedMaxResults > 0)
            {
                finishIndex = parsedStartIndex + parsedMaxResults;

                if (finishIndex > album.Songs.Count - 1)
                {
                    finishIndex = album.Songs.Count - 1;
                }
            }

            for (int index = parsedStartIndex; index <= finishIndex; index++)
            {
                Song song = album.Songs[index];

                if (song.Title != null)
                {
                    SongSyndicationItem item = new SongSyndicationItem(song);
                    items.Add(item);
                }
            }

            feed.Items = items;
            return Utility.GetFormatter(feed);
        }

        /// <summary>
        /// Gets a feed containing albums with the specified details.
        /// </summary>
        /// <param name="title">The album title.</param>
        /// <param name="artist">The album artist.</param>
        /// <param name="startIndex">The index of the first album to include in the results.</param>
        /// <param name="maxResults">The maximum number of albums to return.</param>
        /// <returns>The album feed.</returns>
        public SyndicationFeedFormatter GetAlbums(string title, string artist, string startIndex, string maxResults)
        {
            string decodedTitle = title;

            if (title != null)
            {
                decodedTitle = HttpUtility.UrlDecode(title);
            }

            string decodedArtist = artist;

            if (artist != null)
            {
                decodedArtist = HttpUtility.UrlDecode(artist);
            }

            int parsedStartIndex = 0;
            int.TryParse(startIndex, out parsedStartIndex);

            int parsedMaxResults = 0;
            int.TryParse(maxResults, out parsedMaxResults);

            List<Album> albums = Album.Search(decodedTitle, decodedArtist, parsedStartIndex, parsedMaxResults, false);
            SyndicationFeed feed = new SyndicationFeed();

            string feedTitle = "Album search results";
            string feedDescription = "Search results for albums in the Windows Media Player library";

            if (decodedTitle == null && decodedArtist == null && parsedStartIndex == 0 && parsedMaxResults == 0)
            {
                feedTitle = "All Albums";
                feedDescription = "All albums in the Windows Media Player library";
            }

            feed.Title = new TextSyndicationContent(feedTitle);
            feed.Description = new TextSyndicationContent(feedDescription);
            feed.Links.Add(SyndicationLink.CreateAlternateLink(new Uri("http://code.google.com/p/mediafeeder/wiki/Albums")));
            feed.Generator = XmlString.Generator;
            feed.AttributeExtensions.Add(new XmlQualifiedName(XmlString.ITunesLocalName, XmlString.GenericNameSpace), XmlString.ITunesNamespace);
            feed.AttributeExtensions.Add(new XmlQualifiedName(XmlString.MediaFeederLocalName, XmlString.GenericNameSpace), XmlString.MediaFeederNamespace);
            List<SyndicationItem> items = new List<SyndicationItem>();

            foreach (Album album in albums)
            {
                AlbumSyndicationItem item = new AlbumSyndicationItem(album);
                items.Add(item);
            }

            feed.Items = items;
            return Utility.GetFormatter(feed);
        }

        /// <summary>
        /// Plays the album in Media Center.
        /// </summary>
        public void PlayAlbum(string albumID)
        {
            string decodedAlbumID = HttpUtility.UrlDecode(albumID);

            if (!Album.Exists(decodedAlbumID))
            {
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
                return;
            }

            Album album = new Album(decodedAlbumID);
            album.Play();
        }
    }
}
